# gui/chat_agent.py
"""
GUI聊天智能体 - 集成雷达控制器和大模型自然语言处理
"""

import re
import os
from typing import Dict, Any
from PyQt5.QtCore import QObject, pyqtSignal
from simulator.sim_controller import SimController
from simulator.sim_engine import Target

class GUIChatAgent(QObject):
    """GUI聊天智能体"""

    # 定义信号
    parameter_updated = pyqtSignal(str, float)  # 参数名，参数值

    def __init__(self, sim_controller: SimController):
        super().__init__()
        self.sim_controller = sim_controller
        self.context = {}  # 对话上下文
        self.setup_patterns()
        self.setup_llm()

    def setup_llm(self):
        """设置大模型"""
        self.llm = None
        try:
            # 导入配置
            from radar_config import DASHSCOPE_API_KEY, RADAR_SYSTEM_PROMPT

            # 设置环境变量
            import os
            os.environ['DASHSCOPE_API_KEY'] = DASHSCOPE_API_KEY

            # 尝试导入和初始化大模型
            from llm.qwen_llm import QwenLLM

            if DASHSCOPE_API_KEY and DASHSCOPE_API_KEY != 'your_api_key_here':
                self.llm = QwenLLM()
                self.system_prompt = RADAR_SYSTEM_PROMPT
                print("SUCCESS: 大模型初始化成功")
            else:
                print("WARNING: 未设置DASHSCOPE_API_KEY，将使用规则匹配模式")
        except Exception as e:
            print(f"WARNING: 大模型初始化失败: {e}，将使用规则匹配模式")

    def setup_patterns(self):
        """设置自然语言匹配模式"""
        self.patterns = {
            # 目标管理模式
            'add_target': [
                r'添加.*?目标.*?坐标.*?\((\d+\.?\d*),(\d+\.?\d*),(\d+\.?\d*)\)',
                r'添加.*?(飞机|无人机|目标).*?在.*?(\d+\.?\d*),(\d+\.?\d*),(\d+\.?\d*)',
                r'新建.*?目标.*?位置.*?(\d+\.?\d*)[,，](\d+\.?\d*)[,，](\d+\.?\d*)',
                r'创建.*?目标.*?(\w+).*?(\d+\.?\d*)[,，](\d+\.?\d*)[,，](\d+\.?\d*)'
            ],
            
            # 参数设置模式
            'set_power': [
                r'设置.*?功率.*?(\d+\.?\d*)',
                r'调整.*?功率.*?(\d+\.?\d*)',
                r'功率.*?设为.*?(\d+\.?\d*)',
                r'雷达功率.*?(\d+\.?\d*)'
            ],
            
            'set_frequency': [
                r'设置.*?频率.*?(\d+\.?\d*)',
                r'调整.*?频率.*?(\d+\.?\d*)', 
                r'频率.*?设为.*?(\d+\.?\d*)',
                r'工作频率.*?(\d+\.?\d*)'
            ],
            
            'set_gain': [
                r'设置.*?增益.*?(\d+\.?\d*)',
                r'天线增益.*?(\d+\.?\d*)',
                r'增益.*?调.*?(\d+\.?\d*)'
            ],

            'set_sampling_rate': [
                r'设置.*?采样率.*?(\d+\.?\d*)',
                r'调整.*?采样率.*?(\d+\.?\d*)',
                r'采样率.*?设为.*?(\d+\.?\d*)',
                r'采样频率.*?(\d+\.?\d*)'
            ],

            'set_pulse_width': [
                r'设置.*?脉宽.*?(\d+\.?\d*)',
                r'调整.*?脉宽.*?(\d+\.?\d*)',
                r'脉宽.*?设为.*?(\d+\.?\d*)',
                r'脉冲宽度.*?(\d+\.?\d*)'
            ],

            'set_prt': [
                r'设置.*?PRT.*?(\d+\.?\d*)',
                r'调整.*?PRT.*?(\d+\.?\d*)',
                r'PRT.*?设为.*?(\d+\.?\d*)',
                r'脉冲重复周期.*?(\d+\.?\d*)',
                r'重复时间.*?(\d+\.?\d*)'
            ],

            'set_bandwidth': [
                r'设置.*?带宽.*?(\d+\.?\d*)',
                r'调整.*?带宽.*?(\d+\.?\d*)',
                r'带宽.*?设为.*?(\d+\.?\d*)',
                r'信号带宽.*?(\d+\.?\d*)'
            ],
            
            # 仿真控制模式
            'start_simulation': [
                r'开始仿真',
                r'启动仿真',
                r'开启仿真',
                r'运行仿真'
            ],
            
            'stop_simulation': [
                r'停止仿真',
                r'暂停仿真',
                r'结束仿真'
            ],
            
            'reset_simulation': [
                r'重置仿真',
                r'重启仿真',
                r'清空仿真',
                r'重新开始'
            ],

            # 状态查询模式
            'query_status': [
                r'状态',
                r'查看.*?状态',
                r'显示.*?状态',
                r'仿真.*?情况',
                r'当前.*?状态',
                r'系统.*?状态'
            ],
            
            # 数据管理模式
            'export_data': [
                r'导出数据',
                r'保存数据',
                r'导出.*?结果',
                r'保存.*?结果'
            ],
            
            'clear_targets': [
                r'清空.*?目标',
                r'删除.*?目标',
                r'移除.*?目标',
                r'清除.*?目标'
            ]
        }
        
    def process_message(self, message: str) -> str:
        """处理用户消息并返回回复"""
        message = message.strip()

        try:
            # 优先使用大模型处理
            if self.llm:
                return self._process_with_llm(message)
            else:
                # 回退到规则匹配模式
                return self._process_with_rules(message)

        except Exception as e:
            return f"ERROR: 处理指令时发生错误: {str(e)}"

    def _process_with_llm(self, message: str) -> str:
        """使用大模型处理消息"""
        try:
            # 构建系统提示词
            system_prompt = self._build_system_prompt()

            # 获取当前系统状态
            status_info = self._get_current_status()

            # 构建完整提示词
            full_prompt = f"""{system_prompt}

当前系统状态：
{status_info}

用户输入：{message}

请根据用户输入，生成适当的回复。如果用户想要执行雷达操作，请明确说明具体的操作指令。"""

            # 调用大模型
            response = self.llm.call(full_prompt)

            # 检查是否包含操作指令，如果有则执行
            return self._execute_llm_response(response, message)

        except Exception as e:
            print(f"大模型处理失败: {e}")
            # 直接返回连接失败的信息，不再回退到规则匹配
            return f"ERROR: 大模型服务连接失败: {str(e)}\n\n如需执行雷达操作，请使用具体的命令格式，例如：\n- 开始仿真\n- 添加目标\n- 设置参数"

    def _process_with_rules(self, message: str) -> str:
        """使用规则匹配处理消息"""
        # 尝试各种匹配模式
        for intent, patterns in self.patterns.items():
            for pattern in patterns:
                match = re.search(pattern, message, re.IGNORECASE)
                if match:
                    return self._execute_intent(intent, match, message)

        # 如果没有匹配到模式，尝试直接传递给雷达控制器
        return self._try_direct_command(message)

    def _build_system_prompt(self) -> str:
        """构建系统提示词"""
        return getattr(self, 'system_prompt', """你是一个雷达仿真系统的智能助手。你可以帮助用户：

1. 管理雷达目标（添加、删除目标）
2. 设置雷达参数（功率、频率、增益等）
3. 控制仿真（开始、停止、步进）
4. 查询系统状态
5. 回答关于雷达仿真的问题

请用友好、专业的语调回复用户。如果用户想要执行具体操作，请给出清晰的指令说明。""")

    def _get_current_status(self) -> str:
        """获取当前系统状态信息"""
        try:
            targets_count = len(self.sim_controller.sim_engine.targets)
            sim_time = self.sim_controller.sim_engine.simulation_time
            is_running = self.sim_controller.sim_engine.is_running
            frequency = self.sim_controller.sim_engine.params.get('frequency', 'N/A')
            power = self.sim_controller.sim_engine.params.get('power', 'N/A')

            return f"""目标数量：{targets_count}
仿真时间：{sim_time:.2f}秒
运行状态：{'运行中' if is_running else '已停止'}
工作频率：{frequency} GHz
发射功率：{power} W"""
        except Exception as e:
            return f"状态获取失败：{str(e)}"

    def _execute_llm_response(self, llm_response: str, original_message: str) -> str:
        """处理大模型响应，检查是否需要执行操作"""
        # 检查用户的原始消息是否包含明确的操作指令，而不是检查LLM回复
        original_lower = original_message.lower().strip()

        # 只有当用户原始消息明确表达操作意图时，才尝试执行操作
        if any(keyword in original_lower for keyword in ['添加目标', '设置', '开始仿真', '启动仿真', '停止仿真', '步进']):
            # 尝试使用规则匹配执行具体操作
            rule_result = self._try_extract_and_execute_command(original_message)
            if rule_result and not rule_result.startswith("ERROR:"):
                # 如果成功执行了操作，结合大模型回复和执行结果
                return f"{llm_response}\n\nSUCCESS: 执行结果：{rule_result}"

        return llm_response

    def _try_extract_and_execute_command(self, message: str) -> str:
        """尝试从消息中提取并执行命令"""
        # 使用现有的规则匹配逻辑
        for intent, patterns in self.patterns.items():
            for pattern in patterns:
                match = re.search(pattern, message, re.IGNORECASE)
                if match:
                    return self._execute_intent(intent, match, message)

        # 尝试直接传递给雷达控制器
        if any(keyword in message for keyword in ['添加目标', '雷达参数', '开始仿真', '启动仿真', '停止仿真', '步进']):
            return self.sim_controller.radar_control(message)

        return ""

    def _execute_intent(self, intent: str, match, original_message: str) -> str:
        """执行识别的意图"""
        try:
            if intent == 'add_target':
                return self._handle_add_target(match, original_message)
            elif intent == 'set_power':
                power = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,power,{power}")
                # 发射参数更新信号
                self.parameter_updated.emit('power', power)
                return f"SUCCESS: {response}"
            elif intent == 'set_frequency':
                frequency = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,frequency,{frequency}")
                # 发射参数更新信号
                self.parameter_updated.emit('frequency', frequency)
                return f"SUCCESS: {response}"
            elif intent == 'set_gain':
                gain = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,antenna_gain,{gain}")
                # 发射参数更新信号
                self.parameter_updated.emit('antenna_gain', gain)
                return f"SUCCESS: {response}"
            elif intent == 'set_sampling_rate':
                sampling_rate = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,sampling_rate,{sampling_rate}")
                # 发射参数更新信号
                self.parameter_updated.emit('sampling_rate', sampling_rate)
                return f"SUCCESS: {response}"
            elif intent == 'set_pulse_width':
                pulse_width = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,pulse_width,{pulse_width}")
                # 发射参数更新信号
                self.parameter_updated.emit('pulse_width', pulse_width)
                return f"SUCCESS: {response}"
            elif intent == 'set_prt':
                prt = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,pulse_repetition_time,{prt}")
                # 发射参数更新信号
                self.parameter_updated.emit('pulse_repetition_time', prt)
                return f"SUCCESS: {response}"
            elif intent == 'set_bandwidth':
                bandwidth = float(match.group(1))
                response = self.sim_controller.radar_control(f"雷达参数,bandwidth,{bandwidth}")
                # 发射参数更新信号
                self.parameter_updated.emit('bandwidth', bandwidth)
                return f"SUCCESS: {response}"
            elif intent == 'start_simulation':
                response = self.sim_controller.radar_control("开始仿真")
                return f"START: {response}"
            elif intent == 'stop_simulation':
                response = self.sim_controller.radar_control("停止仿真")
                return f"STOP: {response}"
            elif intent == 'reset_simulation':
                response = self.sim_controller.radar_control("重置仿真")
                return f"RESET: {response}"
            elif intent == 'query_status':
                response = self.sim_controller.radar_control("状态查询")
                return f"STATUS: {response}"
            elif intent == 'export_data':
                response = self.sim_controller.radar_control("导出数据")
                return f"EXPORT: {response}"
            elif intent == 'clear_targets':
                response = self.sim_controller.radar_control("清空目标")  # 需要实现这个功能
                return f"CLEAR: {response}"
                
        except Exception as e:
            return f"ERROR: 执行指令失败: {str(e)}"
    
    def _handle_add_target(self, match, original_message: str) -> str:
        """处理添加目标指令"""
        try:
            groups = match.groups()
            
            # 根据匹配到的信息构建目标
            if len(groups) >= 3:
                x, y, z = float(groups[-3]), float(groups[-2]), float(groups[-1])
                
                # 尝试从消息中提取更多信息
                target_name = self._extract_target_name(original_message)
                velocity = self._extract_velocity(original_message)
                rcs = self._extract_rcs(original_message)
                
                # 构建添加目标指令
                command = f"添加目标,{target_name},{x},{y},{z},{velocity[0]},{velocity[1]},{velocity[2]},{rcs}"
                response = self.sim_controller.radar_control(command)
                
                return f"TARGET: {response}"
            else:
                return "ERROR: 无法解析目标坐标信息"
                
        except Exception as e:
            return f"ERROR: 添加目标失败: {str(e)}"
    
    def _extract_target_name(self, message: str) -> str:
        """从消息中提取目标名称"""
        # 查找目标类型关键词
        aircraft_types = {
            '飞机': '飞机',
            '客机': '客机', 
            '战斗机': '战斗机',
            '无人机': '无人机',
            '直升机': '直升机',
            '目标': '目标'
        }
        
        for keyword, name in aircraft_types.items():
            if keyword in message:
                return name
                
        return '目标'
    
    def _extract_velocity(self, message: str) -> tuple:
        """从消息中提取速度信息"""
        # 查找速度模式
        velocity_patterns = [
            r'速度.*?(\d+\.?\d*)[,，](\d+\.?\d*)[,，](\d+\.?\d*)',
            r'飞行速度.*?(\d+\.?\d*)',
        ]
        
        for pattern in velocity_patterns:
            match = re.search(pattern, message)
            if match:
                groups = match.groups()
                if len(groups) >= 3:
                    return (float(groups[0]), float(groups[1]), float(groups[2]))
                elif len(groups) == 1:
                    speed = float(groups[0])
                    return (speed, speed * 0.7, 0)  # 简单的速度分解
        
        # 默认速度
        return (150, 100, 0)
    
    def _extract_rcs(self, message: str) -> float:
        """从消息中提取RCS信息"""
        rcs_pattern = r'RCS.*?(\d+\.?\d*)'
        match = re.search(rcs_pattern, message, re.IGNORECASE)
        
        if match:
            return float(match.group(1))
        
        # 根据目标类型推断RCS
        if '客机' in message or '大型' in message:
            return 15.0
        elif '战斗机' in message or '小型飞机' in message:
            return 3.5
        elif '无人机' in message:
            return 0.8
        else:
            return 2.0  # 默认值
    
    def _try_direct_command(self, message: str) -> str:
        """尝试直接执行命令"""
        message_lower = message.lower().strip()

        # 处理问候语
        if any(greeting in message_lower for greeting in ['你好', 'hello', 'hi', '您好']):
            return "ASSISTANT: 你好！我是雷达仿真智能助手，很高兴为您服务！\n\n您可以通过自然语言与我交互，比如：\n- 添加目标\n- 设置雷达参数\n- 控制仿真\n\n请告诉我您需要什么帮助？"

        # 处理状态查询
        if any(keyword in message_lower for keyword in ['状态', 'status', '情况', '怎么样']):
            return self._get_system_status()

        # 如果消息看起来像是直接的雷达控制指令
        if any(keyword in message for keyword in ['添加目标', '雷达参数', '天气设置']):
            response = self.radar_controller.radar_control(message)
            return f"COMMAND: {response}"

        # 提供帮助信息
        return self._get_help_message()

    def _get_system_status(self) -> str:
        """获取系统状态"""
        try:
            targets_count = len(self.sim_controller.sim_engine.targets)
            sim_time = self.sim_controller.sim_engine.simulation_time
            is_running = self.sim_controller.sim_engine.is_running

            status_text = f"""STATUS: **雷达仿真系统状态**：

TARGET **目标信息**：
- 当前目标数量：{targets_count} 个
- 仿真时间：{sim_time:.2f} 秒
- 运行状态：{'RUNNING 运行中' if is_running else 'STOPPED 已停止'}

PARAM **雷达参数**：
- 工作频率：{self.sim_controller.sim_engine.params.get('frequency', 'N/A')} GHz
- 发射功率：{self.sim_controller.sim_engine.params.get('power', 'N/A')} W
- 天线增益：{self.sim_controller.sim_engine.params.get('antenna_gain', 'N/A')} dB
- 采样率：{self.sim_controller.sim_engine.params.get('sampling_rate', 'N/A')} MHz
- 脉宽：{self.sim_controller.sim_engine.params.get('pulse_width', 'N/A')} μs
- PRT：{self.sim_controller.sim_engine.params.get('pulse_repetition_time', 'N/A')} ms
- 带宽：{self.sim_controller.sim_engine.params.get('bandwidth', 'N/A')} MHz

INFO: 系统运行正常，随时为您服务！"""
            return status_text
        except Exception as e:
            return f"ERROR: 获取系统状态时出错：{str(e)}"

    def _get_help_message(self) -> str:
        """获取帮助信息"""
        help_text = """ASSISTANT: 我是雷达仿真智能助手，您可以用自然语言与我交互：

TARGET **目标管理**：
- "添加飞机目标在坐标(25,30,5)"
- "添加无人机目标"

PARAM **参数设置**：
- "设置雷达功率为1500瓦"
- "调整频率为12.5GHz"
- "设置采样率为150MHz"
- "设置脉宽为2微秒"
- "调整PRT为1.5毫秒"
- "设置带宽为20MHz"

CONTROL **仿真控制**：
- "开始仿真" / "停止仿真"
- "步进10步"

STATUS **状态查询**：
- "查看状态" / "系统怎么样"

试试对我说"你好"或者直接告诉我您想要做什么！"""

        return help_text
    
    def get_command_suggestions(self, partial_input: str) -> list:
        """根据部分输入获取命令建议"""
        suggestions = []
        
        if '添加' in partial_input:
            suggestions.extend([
                "添加飞机目标在坐标(25,30,5)",
                "添加无人机目标位置15,20,3",
                "添加客机目标坐标(40,-15,8)"
            ])
        elif '设置' in partial_input:
            suggestions.extend([
                "设置雷达功率为1500瓦",
                "设置频率为12.5GHz",
                "设置天线增益为35dB",
                "设置采样率为150MHz",
                "设置脉宽为2微秒",
                "设置PRT为1.5毫秒",
                "设置带宽为20MHz"
            ])
        elif '开始' in partial_input or '启动' in partial_input:
            suggestions.extend([
                "开始仿真",
                "启动仿真并运行5步"
            ])
        else:
            suggestions.extend([
                "查看仿真状态",
                "添加目标",
                "开始仿真",
                "步进5步"
            ])
            
        return suggestions[:5]  # 返回最多5个建议